from celery.task import task
import models
import pycurl
import json
import graph_relaxation
import datetime
import time
from pyvotecore.schulze_method import SchulzeMethod


@task
def add(x, y):
    return x + y


@task
def initialize_website(website, check_db=True):

    """
    *check_db= True if you want to save to mongo
    Task to Initialize Website for Agent Web Service
    Runs through the following process:
        *Grabs all users, content, and vote ids
        *Iterates through atomic item:
            *Stores information in database
    """

    info = models.get_from_registrar(website, ['hooks'])

    initialize_users(info, website, check_db)

    initialize_content(info, website, check_db)

    initialize_votes(info, website, check_db)


@task
def initialize_users(info, website, check_db):
    ###First aggregate users into the database
    user_pks = info['hooks']['user_pk']
    user_ids = get_http_object(str(website + user_pks))
    user_ids = json.loads(user_ids)

    for user in user_ids:
        if not models.has_item(website, 'user', user) and check_db:
            user = get_http_object(str(website +
                                info['hooks']['get_user'] % user))
            user = json.loads(user)
            models.save_item(website, 'user', user)


@task
def initialize_content(info, website, check_db):
    ###Aggregate Content
    cont_pks = info['hooks']['content_pk']
    cont_ids = get_http_object(str(website + cont_pks))
    cont_ids = json.loads(cont_ids)

    for ctype in cont_ids:
        parameters = ctype['params']
        ids = ctype['ids']
        for i in ids:
            if not models.has_item(website, 'content', i['pk']) and check_db:
                params = tuple(parameters + [i['pk']])
                api_str = info['hooks']['get_content'] % params
                val = get_http_object(str(website + api_str))
                to_save = json.loads(val)
                to_save['params'] = parameters
                models.save_item(website, 'content', to_save)


@task
def initialize_votes(info, website, check_db, update=False):
    ###Aggregate votes
    vote_pks = info['hooks']['vote_pk']
    vote_ids = get_http_object(str(website + vote_pks))
    vote_ids = json.loads(vote_ids)

    for ctype in vote_ids:
        parameters = ctype['params']
        ids = ctype['ids']
        for i in ids:
            params = tuple(parameters + [i['pk']])
            api_str = info['hooks']['get_vote'] % params
            print str(website + api_str)
            val = get_http_object(str(website + api_str))
            print val
            val = json.loads(val)
            if 'error' not in val:
                val['params'] = parameters
                models.save_item(website, 'vote', val)


@task
def update(website, key, updatetype, params):
    if models.verify_key(website, key):
        coll_name = 'get_' + updatetype
        info = models.get_from_registrar(website, ['hooks'])
        api_str = info['hooks'][coll_name] % tuple(params)
        update_finish(website, api_str, updatetype)
        return True, None
    else:
        return False, 'Incorrect Verification Key'


@task(ignore_result=True)
def update_finish(website, api_str, updatetype):
    obj = get_http_object(str(website + api_str))
    obj = json.loads(obj)
    models.update_item(website, updatetype, obj)


def check_time(timestr):
    time_val = time.strptime(timestr.replace('-', ' '), "%Y %m %d %H:%M:%S")
    dt = datetime.datetime.fromtimestamp(time.mktime(time_val))
    now = datetime.datetime.now()
    delta = now - dt
    diff = 24 * 60 * 60 * delta.days + delta.seconds + delta.microseconds / 1000000.
    if diff < 0:
        return True
    return False


@task
def candidate_platforms(website, obj_id, k):
    ###first we need to grab all the candidate platforms and setup the network
    obj = get_http_object(str(website + '/api/platforms/' + str(obj_id)))
    obj = json.loads(obj)
    for platformdim in obj:
        if platformdim['dimension']['complete'] == False:
            # also need to check to see if candidate generation has passed
            if check_time(platformdim['dimension']['deadline_dt']):
                #get groupcontent
                app_label = platformdim['app_label']
                model = platformdim['model']
                groupcontent = get_http_object(str(website + '/api/groupcontent/' + str(obj_id) + '/'))
                groupcontent = json.loads(groupcontent)
                relevant_content = groupcontent[app_label + '_' + model]
                #get votes for each content type
                votes = []
                for rel in relevant_content:
                    vote = models.get_item(website, 'vote', {'content_id': rel['id']})
                    if vote != None:
                        for i in vote:
                            votes.append(vote)
                #get platforms!
                hook = str(website + '/api/platforms/%s/%s/%s/' % (app_label, model, obj_id))
                user_platforms = get_http_object(hook)
                user_platforms = json.loads(user_platforms)
                print 'running graph relaxation'
                results = graph_relaxation.generate_candidates(website, votes, relevant_content, user_platforms, k)
                #process results, Sets are not JSON serializable
                return [list(s) for s in results]


@task
def schulze_method(ballots):
    """This uses pyvotecore schulze method and exposes that via the RPC
    """
    return SchulzeMethod([
          {"count":3, "ballot":[["A"], ["C"], ["D"], ["B"]]},
          {"count":9, "ballot":[["B"], ["A"], ["C"], ["D"]]},
          {"count":8, "ballot":[["C"], ["D"], ["A"], ["B"]]},
          {"count":5, "ballot":[["D"], ["A"], ["B"], ["C"]]},
          {"count":5, "ballot":[["D"], ["B"], ["C"], ["A"]]}
        ], ballot_notation="grouping").as_dict()


@task
def test_service(website):
    """
    Iterate through each hook and verify JSON output
    """

    pass


def get_http_object(website):
    c = pycurl.Curl()
    c.setopt(pycurl.URL, website)
    #c.setopt(pycurl.HTTPHEADER, ["Accept:"])
    import StringIO
    b = StringIO.StringIO()
    c.setopt(pycurl.WRITEFUNCTION, b.write)
    #c.setopt(pycurl.FOLLOWLOCATION, 1)
    #c.setopt(pycurl.MAXREDIRS, 5)
    c.perform()
    return b.getvalue()
